package com.polaris.live.dialog

import android.content.Context
import android.view.MotionEvent
import android.view.View
import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.StringUtils
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.CenterPopupView
import com.polaris.live.R
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.constant.CommonConst
import com.polaris.live.common.constant.PagConst
import com.polaris.live.common.ext.setOnSingleClickListener
import com.polaris.live.common.manager.startCountdown
import com.polaris.live.common.mvvm.viewmodel.BaseViewModel
import com.polaris.live.common.network.manualRequest
import com.polaris.live.common.util.LogExt
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.constant.LiveConst
import com.polaris.live.constant.UserConst
import com.polaris.live.databinding.DialogStartPartyMatchBinding
import com.polaris.live.net.homeService
import com.polaris.live.popup.GlobalPopupManager
import com.polaris.live.resp.back_resp.MatchStartResp
import com.polaris.live.resp.back_resp.PartyGameResp
import com.polaris.live.resp.bean.HomeSelectTypeBean
import com.polaris.live.resp.go_resp.EndMatchBean
import com.polaris.live.resp.go_resp.MatchIdBean
import com.polaris.live.resp.go_resp.MatchStartBean
import com.polaris.live.translation.R.string
import com.polaris.live.utils.UserUtils.isLevelZero
import com.polaris.live.utils.route.RoutePath
import com.polaris.live.utils.route.Router
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch

/**
 * 派对匹配
 *
 * @author Created by 半仙 on 2024/3/20/020 9:41
 */
class StartPartyMatchDialog(
    context: Context,
    private val mViewModel: BaseViewModel,
    private val mPartyGame: PartyGameResp,
    private val mAssetType: Int?,
    private val mMaxPrice: Long?,
    private val mMuteSound: Boolean,
    private val mOnCreateRoom: () -> Unit,
) : CenterPopupView(context) {

    override fun getImplLayoutId() = R.layout.dialog_start_party_match

    private lateinit var mBinding: DialogStartPartyMatchBinding

    private var mMatchId: Long? = null
    private var mEndMatch = true

    private var mMatchStartJob: Job? = null
    private var mMatchingJob: Job? = null
    private var mMatchChangeJob: Job? = null

    override fun onCreate() {
        super.onCreate()
        mBinding = DialogStartPartyMatchBinding.bind(popupImplView)

        mBinding.loadingPag.apply {
            path = PagConst.PAGE_CHANGE_LOADING_PAG
            setRepeatCount(-1)
            play()
        }

        mBinding.ivClose.setOnSingleClickListener {
            endMatch(CommonConst.MatchEnd.MANUAL)

            dismiss()
        }

        mBinding.createParty.setOnSingleClickListener {
            endMatch(CommonConst.MatchEnd.MANUAL)

            mOnCreateRoom()
            dismiss()
        }

        mBinding.otherGame.setOnSingleClickListener(1000) {
            changeOtherGame()
        }

        startGameMatch(mPartyGame.id)
    }

    private fun startGameMatch(gameType: Int?) {
        val matchBean = MatchStartBean(
            CommonConst.MatchStart.GAEM_MATCH,
            UserConst.From.MATCH,
            mAssetType,
            gameType,
            mMaxPrice
        )
        mMatchStartJob = mViewModel.viewModelScope.launch {
            try {
                manualRequest({ homeService.matchStart(matchBean) }, {
                    mMatchId = it.id
                    mEndMatch = false

                    startHeartbeat(it.id)
                }, {
                    ToastGravity.showGravity(it.errorMsg)

                    dismiss()
                })
            } finally {
                if (mMatchStartJob == coroutineContext[Job]) {
                    mMatchStartJob = null
                }
            }
        }
    }

    //匹配心跳
    private fun startHeartbeat(matchId: Long) {
        val maxInterval = 5000L
        mMatchingJob =
            mViewModel.viewModelScope.startCountdown(Long.MAX_VALUE, maxInterval / 2 + 50, { time ->
                manualRequest({ homeService.matchHeartbeat(MatchIdBean(matchId)) }, {
                    //超过3次显示创建房间和切换游戏
                    val duration = (Long.MAX_VALUE - time)
                    if (duration >= maxInterval) {
                        mBinding.llBottom.visibility = View.VISIBLE
                    }

                    if (it.user != null) {
                        endMatch(CommonConst.MatchEnd.END_MATCH)
                        Router.builder(RoutePath.PARTY_GAME_SPECTATOR_ACTIVITY)
                            .withLong("anchorId", it.user.base.userId)
                            .withBoolean(LiveConst.Params.IS_MATCH_COME_GAME, true)
                            .withBoolean(LiveConst.Params.SOUND_STATUS, mMuteSound)
                            .navigation(context)
                        dismiss()
                    }
                }, {
                    if (!isDismiss) {
                        ToastGravity.showGravity(it.errorMsg)
                    }
                })
            }, {
                if (mMatchingJob == coroutineContext[Job]) {
                    mMatchingJob = null
                }
            })
    }

    //切换游戏匹配
    private fun changeOtherGame() {
        cancelJob()

        mBinding.llBottom.visibility = View.GONE
        ToastGravity.showGravity(StringUtils.getString(string.again_match_user))

        //结束匹配
        mMatchChangeJob = endMatch(CommonConst.MatchEnd.MANUAL) {
            startGameMatch(null)
        }
    }

    //结束匹配
    private fun endMatch(endType: Int, success: (() -> Unit)? = null): Job? {
        val matchId = mMatchId
        return if (matchId == null) {
            success?.invoke()

            null
        } else {
            if (mEndMatch) {
                success?.invoke()
                return null
            }
            mEndMatch = true

            mViewModel.viewModelScope.launch {
                try {
                    try {
                        homeService.endMatch(
                            EndMatchBean(
                                matchId,
                                endType
                            )
                        )
                    } catch (t: Throwable) {
                        LogExt.logE("endMatch", t)
                    }
                } finally {
                    if (mMatchChangeJob == coroutineContext[Job]) {
                        mMatchChangeJob = null
                    }

                    success?.invoke()
                }
            }
        }
    }

    private fun cancelJob() {
        mMatchStartJob?.cancel()
        mMatchStartJob = null

        mMatchingJob?.cancel()
        mMatchingJob = null

        mMatchChangeJob?.cancel()
        mMatchChangeJob = null
    }

    override fun onBackPressed(): Boolean {
        endMatch(CommonConst.MatchEnd.MANUAL)
        return super.onBackPressed()
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        endMatch(CommonConst.MatchEnd.MANUAL)
        return super.onInterceptTouchEvent(ev)
    }

    override fun onDismiss() {
        cancelJob()

        super.onDismiss()
    }

    companion object {

        /**
         * 显示匹配dialog
         */
        fun showDialog(
            context: Context,
            viewModel: BaseViewModel,
            gameResp: PartyGameResp,
            selectAssetType: Int?,
            selectPrice: Long?,
            muteSound: Boolean,
        ) {
            XPopup.Builder(context)
                .hasShadowBg(true)
                .isDestroyOnDismiss(true)
                .asCustom(
                    StartPartyMatchDialog(
                        context,
                        viewModel,
                        gameResp,
                        selectAssetType,
                        selectPrice,
                        muteSound
                    ) {
                        val assetType = if (UserManager.getUser().isLevelZero()) {
                            CommonConst.PartyAssetType.FREE
                        } else {
                            selectAssetType ?: CommonConst.PartyAssetType.COIN
                        }
                        val price = if (assetType == CommonConst.PartyAssetType.FREE) {
                            0L
                        } else {
                            selectPrice ?: gameResp.prices.find {
                                it.assetType == CommonConst.PartyAssetType.COIN
                            }?.prices?.firstOrNull() ?: 0L
                        }

                        GlobalPopupManager.showCompletePopup(context, isOk = {
                            val homeSelectTypeBean = HomeSelectTypeBean(
                                gameResp.id,
                                assetType,
                                price
                            )
                            Router.builder(RoutePath.SET_PARTY_COVER_ACTIVITY)
                                .withInt("gameId", homeSelectTypeBean.gameId)
                                .withInt("rewardType", homeSelectTypeBean.rewardType)
                                .withLong("rewardNum", homeSelectTypeBean.rewardNum)
                                .navigation()
                        })
                    }
                )
                .show()
        }

    }

    class StartPartyMatchDialogBean(
        val startResp: MatchStartResp,
        val gameResp: PartyGameResp,
        val startBean: MatchStartBean,
    )
}